package xcmg.device.service.order;


import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import xcmg.device.dao.entity.company.CompanyInfoDO;
import xcmg.device.dao.entity.order.GpsMmSwOrderDO;
import xcmg.device.dao.entity.order.GpsMmSwOrderDetailDO;
import xcmg.device.dao.entity.order.GpsMmSwOrderLabelDO;
import xcmg.device.dao.mapper.order.GpsMmSwOrderDetailMapper;
import xcmg.device.dao.mapper.order.GpsMmSwOrderLabelMapper;
import xcmg.device.dao.mapper.order.GpsMmSwOrderMapper;
import xcmg.device.infra.BeanUtil;
import xcmg.device.service.company.CompanyInfoService;
import xcmg.device.service.vo.order.GpsMmSwOrderDetailVO;
import xcmg.device.service.vo.order.GpsMmSwOrderVO;
import xcmg.syn.feign.SynClient;
import xcmg.syn.service.vo.order.MmSwOrderDetailVO;
import xcmg.syn.service.vo.order.MmSwOrderLabelVO;
import xcmg.syn.service.vo.order.MmSwOrderVO;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.util.PageHelperPlus;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * GpsMmSwOrder 后台接口实现类
 */
@Slf4j
@Service
public class GpsMmSwOrderService {

    @Autowired
    private SynClient synClient;

    @Autowired
    private GpsMmSwOrderMapper gpsMmSwOrderMapper;

    @Autowired
    private GpsMmSwOrderDetailMapper gpsMmSwOrderDetailMapper;

    @Autowired
    private GpsMmSwOrderLabelMapper gpsMmSwOrderLabelMapper;

    @Autowired
    private CompanyInfoService companyInfoService;

    @Autowired
    private SubcontractingOrderService subcontractingOrderService;

    private static final int BATCH_SIZE = 5000;

    public PageCommonVO<GpsMmSwOrderVO> list(SearchCommonVO<GpsMmSwOrderVO> condition) {
        PageCommonVO<GpsMmSwOrderVO> result = new PageCommonVO<>();
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
//                PageHelperPlus.orderBy("create_date desc");
        List<GpsMmSwOrderVO> resultList = gpsMmSwOrderMapper.queryList(condition.getFilters());
        result.setPageInfo(new PageInfo(resultList));
        List<GpsMmSwOrderVO> voList = collectList(resultList);
        result.setPageInfoList(voList);
        return result;
    }

    private List<GpsMmSwOrderVO> collectList(List<GpsMmSwOrderVO> resultList) {
        if (null == resultList || resultList.size() == 0) {
            return Collections.emptyList();
        }
        List<GpsMmSwOrderVO> r = new ArrayList<>(resultList.size());
        List<Long> ids = resultList.stream().map(GpsMmSwOrderVO::getOrderId).collect(Collectors.toList());
        Map<Long, List<GpsMmSwOrderDetailVO>> detailMap = queryDetailMap(ids);
        for (GpsMmSwOrderVO vo : resultList) {
            List<GpsMmSwOrderDetailVO> detailList = detailMap.get(vo.getOrderId());
            if (null != detailList) {
                vo.setOrderDetailList(detailList);
            }
            r.add(vo);
        }
        return r;
    }

    private Map<Long, List<GpsMmSwOrderDetailVO>> queryDetailMap(List<Long> ids) {
        if (null == ids || ids.size() == 0) {
            return Collections.emptyMap();
        }
        Map<Long, List<GpsMmSwOrderDetailVO>> r = new HashMap<>(ids.size());
        Lists.partition(ids, 1000).forEach(subIds -> {
            GpsMmSwOrderDetailVO dv = new GpsMmSwOrderDetailVO();
            dv.setOrderIds(subIds);
            List<GpsMmSwOrderDetailVO> ll = gpsMmSwOrderDetailMapper.queryList(dv);
            r.putAll(ll.stream().collect(Collectors.groupingBy(GpsMmSwOrderDetailVO::getOrderId)));
        });
        return r;
    }

    public GpsMmSwOrderVO getById(Long id) {
        GpsMmSwOrderVO vo = new GpsMmSwOrderVO();
        vo.setOrderId(id);
        List<GpsMmSwOrderVO> resultList = gpsMmSwOrderMapper.queryList(vo);
        collectList(resultList);
        if (null != resultList && resultList.size() > 0) {
            return resultList.get(0);
        }
        return null;
    }


    public void doSyncGpsMmSwOrder(Date t, String querySupplierNo, boolean allSupplier) {
        log.info("doSyncGpsMmSwOrder,t:{},querySupplierNo:{}", t, querySupplierNo);
        Map<String, CompanyInfoDO> companyCache = new HashMap<>();
        if (null == querySupplierNo && allSupplier) {
            companyCache.putAll(companyInfoService.queryCommpanyInfo(null));
        }

        MmSwOrderVO voParam = new MmSwOrderVO();
        Long maxOrderId = null;
        while (true) {
            //如果有时间，根据时间增量同步
            voParam.setLastModifiedTimeStart(t);
            voParam.setLimitNum(BATCH_SIZE);
            voParam.setSupplierNo(querySupplierNo);
            voParam.setMinOrderId(maxOrderId);
            ActionResult<List<MmSwOrderVO>> listActionResult = synClient.listMmSwOrderVO(voParam);
            if (listActionResult.getCode() != 0) {
                log.error("同步GPS数据失败,voParam：{},\n listActionResult:{}", voParam, listActionResult);
                break;
            }
            List<MmSwOrderVO> orders = listActionResult.getValue();
            if (CollectionUtils.isEmpty(orders)) {
                log.info("没有需要同步的GPS数据");
                break;
            }
            boolean fullPage = (orders.size() == BATCH_SIZE);
            maxOrderId = orders.get(orders.size() - 1).getOrderId();
            if (companyCache.isEmpty() || !allSupplier) {
                //没有明细行
                Set<String> suplierNos = orders.stream().filter(o -> CollectionUtils.isNotEmpty(o.getMmSwOrderDetailVOList()))
                        .map(MmSwOrderVO::getSupplierNo).collect(Collectors.toSet());
                if (suplierNos.isEmpty()) {
                    log.error("剔除无明细行后，供应商空，本次不执行。voParam: {}", voParam);
                    continue;
                }
                query2CompanyCache(companyCache, suplierNos);
            }
            if (companyCache.isEmpty()) {
                log.error("没有找到对应的供应商");
                continue;
            }
            List<MmSwOrderVO> okList = new ArrayList<>(orders.size());
            for (MmSwOrderVO mvo : orders) {
                CompanyInfoDO companyInfoDO = companyCache.get(mvo.getSupplierNo());
                if (null == companyInfoDO) {
                    log.error("没有找到对应的供应商,{}", mvo);
                    continue;
                }
                mvo.setOrgId(companyInfoDO.getOrgId());
                mvo.setSupplierName(companyInfoDO.getCompanyName());
                okList.add(mvo);
            }
            if (CollectionUtils.isNotEmpty(okList)) {
                Date now = new Date();
                Lists.partition(okList, 50).forEach(subOrders -> {
                    List<GpsMmSwOrderDO> hl = new ArrayList<>();
                    List<GpsMmSwOrderDetailDO> bl = new ArrayList<>();
                    List<GpsMmSwOrderLabelDO> ll = new ArrayList<>();
                    subOrders.forEach(o -> {
                        if (CollectionUtils.isNotEmpty(o.getMmSwOrderDetailVOList())) {
                            for (MmSwOrderDetailVO detailVO : o.getMmSwOrderDetailVOList()) {
                                GpsMmSwOrderDetailDO d = BeanUtil.do2bo(detailVO, GpsMmSwOrderDetailDO.class);
                                d.setUpdateTime(now);
                                d.setOrgId(o.getOrgId());
                                bl.add(d);
                            }
                            GpsMmSwOrderDO m = BeanUtil.do2bo(o, GpsMmSwOrderDO.class);
                            m.setUpdateTime(now);
                            hl.add(m);
                        }
                        if (CollectionUtils.isNotEmpty(o.getLabelList())) {
                            for (MmSwOrderLabelVO labelVO : o.getLabelList()) {
                                GpsMmSwOrderLabelDO l = BeanUtil.do2bo(labelVO, GpsMmSwOrderLabelDO.class);
                                l.setOrgId(o.getOrgId());
                                ll.add(l);
                            }
                        }
                    });
                    try {
                        if (CollectionUtils.isNotEmpty(hl)) {
                            gpsMmSwOrderDetailMapper.batchSave(bl);
                            gpsMmSwOrderMapper.batchSave(hl);
                        }
                    } catch (Exception e) {
                        log.error("同步GPS数据失败,voParam：{}", voParam, e);
                        throw new RuntimeException(e);
                    }
                    try {
                        if (CollectionUtils.isNotEmpty(ll)) {
                            gpsMmSwOrderLabelMapper.batchInsert(ll);
                            //根据条码的信息生成转包单
                            subcontractingOrderService.createZbdByBarcode(ll);
                        }
                    } catch (Exception e) {
                        log.error("同步GPS数据-（条码数据）失败,voParam：{}", voParam, e);
                        throw new RuntimeException(e);
                    }
                });
            }
            if (!fullPage) {
                log.info("当前查询不满页,同步GPS数据完成,size:{}", orders.size());
                break;
            } else {
                log.info("当前查询满页,maxOrderId:{}", maxOrderId);
            }
        }
    }

    public void query2CompanyCache(Map<String, CompanyInfoDO> companyCache, Set<String> suplierNos) {
        if (companyCache.isEmpty() && CollectionUtils.isNotEmpty(suplierNos)) {
            Map<String, CompanyInfoDO> map=companyInfoService.queryCommpanyInfo(new ArrayList<>(suplierNos));
            companyCache.putAll(map);
            return;
        }
        if (CollectionUtils.isNotEmpty(suplierNos)) {
            Set<String> noe = suplierNos.stream().filter(s -> !companyCache.containsKey(s)).collect(Collectors.toSet());
            if (CollectionUtils.isNotEmpty(noe)) {
                companyCache.putAll(companyInfoService.queryCommpanyInfo(new ArrayList<>(noe)));
            }
        }
    }

    public Map<Long, GpsMmSwOrderVO> queryMaps(List<Long> orderIds) {
        if (CollectionUtils.isEmpty(orderIds)) {
            return new HashMap<>();
        }
        Map<Long, GpsMmSwOrderVO> r = new HashMap<>();
        Lists.partition(orderIds, 1000).forEach(subOrderIds -> {
            GpsMmSwOrderVO vo = new GpsMmSwOrderVO();
            vo.setOrderIds(subOrderIds);
            List<GpsMmSwOrderVO> resultList = gpsMmSwOrderMapper.queryList(vo);
            if (CollectionUtils.isNotEmpty(resultList)) {
                resultList.forEach(o -> r.put(o.getOrderId(), o));
            }
        });
        return r;
    }
}
